package com.tarena.luban.worker.server.repo.impl;

import com.alibaba.fastjson.JSON;
import com.sun.corba.se.spi.orbutil.threadpool.Work;
import com.tarena.luban.worker.server.bo.WorkerAreaBO;
import com.tarena.luban.worker.server.dao.WorkerAreaDao;
import com.tarena.luban.worker.server.repo.AbstractCacheRepository;
import com.tarena.luban.worker.server.repo.WorkerAreaRepository;
import com.tarena.luban.worker.server.repo.converter.WorkerAreaConverter;
import com.tarena.tp.luban.worker.po.WorkerArea;
import com.tarena.tp.luban.worker.server.dto.param.WorkerAreaParam;
import com.tarena.tp.luban.worker.server.dto.param.WorkerCreateParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Repository
@Slf4j
public class WorkerAreaRepoImpl extends AbstractCacheRepository<WorkerAreaBO> implements WorkerAreaRepository {
    @Autowired
    private WorkerAreaDao workerAreaDao;
    @Autowired
    private WorkerAreaConverter workerAreaConverter;
    @Override
    public void saveWorkerArea(WorkerCreateParam workerCreateParam) {
        List<WorkerAreaParam> workerAreaParams = workerCreateParam.getWorkerAreaParams();
        //循环封装一下参数userId
        for (WorkerAreaParam workerAreaParam : workerAreaParams) {
            workerAreaParam.setUserId(workerCreateParam.getUserId());
        }
        //方案一 循环 每次写一个 insert into table (字段) values (#{}),(#{}),(#{})
        //方案二 批量 一次insert 写一堆 insert into table (字段) values (),(),()
        List<WorkerArea> workerAreas = workerAreaConverter.params2pos(workerAreaParams);
        // 动态sql标签 <if> <foreach>
        workerAreaDao.insertAreas(workerAreas);
    }
    //业务key值前缀

    @Override
    public List<WorkerAreaBO> getWorkerAreasByUserId(Long userId) {
        String areasKey="worker:area:bos:"+userId;
        //判断存在
        Boolean hasKey = stringRedisTemplate.hasKey(areasKey);
        if (hasKey){
            return getCaches(areasKey);
        }else {
            //设置一个锁
            String aresLockKey=areasKey+".lock";
            String randCode=new Random().nextInt(9000)+1000+"";
            try{
            Boolean tryLock = opsForValue.setIfAbsent(aresLockKey, randCode, 10, TimeUnit.SECONDS);
            if (!tryLock){
                //没抢到
                Thread.sleep(3000);
                return getCaches(areasKey);
            }
            //有可能查询一个空值,入驻师傅的时候,提交的数据中没有区域信息
            List<WorkerArea> areas=workerAreaDao.selectAreasByUserId(userId);
            if (areas== null || areas.size()==0){
                return null;
            }else{
                List<WorkerAreaBO> workerAreaBOS = workerAreaConverter.poList2BoList(areas);
                //补充一下缓存
                setCaches(areasKey,workerAreaBOS,
                        60*60*24+Long.parseLong(new Random().nextInt(60*60*24)+""),
                        TimeUnit.SECONDS);
                return workerAreaBOS;
            }}catch (Exception e){
                log.error("缓存抢锁,读取数据库,补充缓存报错",e);
                return null;
            }finally {
                //释放锁
                //读取 锁的value值,判断和randCode是否一致
                //只有一致的情况下才会释放
                String cacheRand = opsForValue.get(aresLockKey);
                if (cacheRand!=null && cacheRand.equals(randCode)){
                    stringRedisTemplate.delete(aresLockKey);
                }
            }
        }
    }

    @Override
    public void deleteWorkerArea(Long userId) {
        workerAreaDao.delete(userId);
    }

    @Override
    protected String searialize(WorkerAreaBO workerAreaBO) {
        return JSON.toJSONString(workerAreaBO);
    }

    @Override
    protected WorkerAreaBO desearialize(String json) {
        return JSON.toJavaObject(JSON.parseObject(json),WorkerAreaBO.class);
    }
}
